package com.chenfan.magic.core;

import com.alibaba.fastjson.JSON;
import com.chenfan.magic.base.R;
import com.chenfan.magic.constant.EventConstant;
import com.chenfan.magic.entity.LogMagicExecuter;
import com.chenfan.magic.entity.LogMagicExecuterResult;
import com.chenfan.magic.entity.LogMagicInterpreter;
import com.chenfan.magic.entity.LogMagicResolver;
import com.chenfan.magic.tags.events.MagicLogEvent;
import com.chenfan.magic.utils.*;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 魔方引擎日志信息事件发送
 *
 * @author troy
 */
public class MagicLogPublisher {

    public static final String SIGN_EXECUTER = "executer";
    public static final String SIGN_EXECUTER_RESULT = "executer_result";
    public static final String SIGN_RESOLVER = "resolver";
    public static final String SIGN_INTERPRETER = "interpreter";

    /**
     * 解释器器日志
     *
     * @param type
     * @param code
     * @param result
     * @param paramMap
     * @param ttl
     * @param error
     */
    public static void publishInterpreterEvent(String type, String code, Object result, Map<String, Object> paramMap, String ttl, Throwable error, boolean failed) {
        HttpServletRequest request = WebKit.getRequest();
        LogMagicInterpreter logMagic = new LogMagicInterpreter();
        logMagic.setInterpretType(type);
        logMagic.setInterpretCode(code);
        logMagic.setInterpretResult(JSON.toJSONString(result));
        logMagic.setInterpretParamMap(FastJsonKit.map2Jsonstring(paramMap));
        logMagic.setInterpretTtl(ttl);
        logMagic.setInterpretStatus(1);
        if (Func.isNotEmpty(error)) {
            logMagic.setInterpretStatus(0);
            logMagic.setInterpretException(Exceptions.getStackTraceAsString(error));
        }
        if (failed) {
            logMagic.setInterpretStatus(0);
        }

        Map<String, Object> event = new HashMap<>(16);
        event.put(EventConstant.EVENT_LOG, logMagic);
        event.put(EventConstant.EVENT_SIGN, SIGN_INTERPRETER);
        event.put(EventConstant.EVENT_REQUEST, request);
        SpringUtil.publishEvent(new MagicLogEvent(event));
    }

    public static void publishInterpreterEvent(String type, String code, Object result, Map<String, Object> paramMap, String ttl) {
        publishInterpreterEvent(type, code, result, paramMap, ttl, null, false);
    }

    public static void publishInterpreterEvent(String type, String code, Object result, Map<String, Object> paramMap, String ttl, Throwable error) {
        publishInterpreterEvent(type, code, result, paramMap, ttl, error, Func.isNotEmpty(error));
    }


    /**
     * 解析器日志
     *
     * @param type
     * @param template
     * @param result
     * @param paramMap
     * @param ttl
     * @param error
     */
    public static void publishResolverEvent(String type, String template, String result, Map<String, Object> paramMap, String ttl, Throwable error) {
        HttpServletRequest request = WebKit.getRequest();
        LogMagicResolver logMagic = new LogMagicResolver();
        logMagic.setResolveType(type);
        logMagic.setResolveTemplate(template);
        logMagic.setResolveResult(result);
        logMagic.setResolveParamMap(FastJsonKit.map2Jsonstring(paramMap));
        logMagic.setResolveTtl(ttl);
        logMagic.setResolveStatus(1);
        if (Func.isNotEmpty(error)) {
            logMagic.setResolveStatus(0);
            logMagic.setResolveException(Exceptions.getStackTraceAsString(error));
        }

        Map<String, Object> event = new HashMap<>(16);
        event.put(EventConstant.EVENT_LOG, logMagic);
        event.put(EventConstant.EVENT_SIGN, SIGN_RESOLVER);
        event.put(EventConstant.EVENT_REQUEST, request);
        SpringUtil.publishEvent(new MagicLogEvent(event));
    }

    public static void publishResolverEvent(String type, String template, String result, Map<String, Object> paramMap, String ttl) {
        publishResolverEvent(type, template, result, paramMap, ttl, null);
    }


    /**
     * 执行器日志
     *
     * @param executeId
     * @param executeType
     * @param executeLine
     * @param mqlId
     * @param mqlVersion
     * @param mqlContext
     * @param mqlComplex
     */
    public static void publishExecuterEvent(String executeId, Integer executeType, Integer executeLine, String mqlId, String mqlVersion, String mqlContext, String mqlComplex) {
        HttpServletRequest request = WebKit.getRequest();
        LogMagicExecuter logMagic = new LogMagicExecuter();
        logMagic.setExecuteId(StringKit.isNotBlank(executeId) ? executeId : (IDKit.snowFlake() + "" + System.currentTimeMillis()));
        logMagic.setExecuteType(executeType);
        logMagic.setExecuteLine(executeLine);
        logMagic.setExecuteStartTime(new Date());
        logMagic.setMqlId(mqlId);
        logMagic.setMqlVersion(mqlVersion);
        logMagic.setMqlContext(mqlContext);
        logMagic.setMqlComplex(mqlComplex);

        Map<String, Object> event = new HashMap<>(16);
        event.put(EventConstant.EVENT_LOG, logMagic);
        event.put(EventConstant.EVENT_SIGN, SIGN_EXECUTER);
        event.put(EventConstant.EVENT_REQUEST, request);
        SpringUtil.publishEvent(new MagicLogEvent(event));
    }

    public static void publishExecuterResultEvent(String executeId, String isvWebhooks, String resultScope, String resultRes, String resultDesc, Throwable error) {
        HttpServletRequest request = WebKit.getRequest();
        //1-成功, 0 失败.
        int statusCode = Func.isNotEmpty(error) ? 0 : 1;
        LogMagicExecuterResult logMagicResult = new LogMagicExecuterResult();
        logMagicResult.setResultStatus(statusCode);
        logMagicResult.setExecuteId(StringKit.isNotBlank(executeId) ? executeId : (IDKit.snowFlake() + "" + System.currentTimeMillis()));
        logMagicResult.setExecuteEndTime(new Date());
        logMagicResult.setResultScopes(resultScope);
        logMagicResult.setResultRes(resultRes);
        logMagicResult.setResultDesc(resultDesc);

        if (Func.isNotEmpty(error)) {
            logMagicResult.setStackTrace(Exceptions.getStackTraceAsString(error));
            logMagicResult.setExceptionName(error.getClass().getName());
            logMagicResult.setMessage(error.getMessage());
            StackTraceElement[] elements = error.getStackTrace();
            if (Func.isNotEmpty(elements)) {
                StackTraceElement element = elements[0];
                logMagicResult.setMethodName(element.getMethodName());
                logMagicResult.setMethodClass(element.getClassName());
                logMagicResult.setFileName(element.getFileName());
                logMagicResult.setLineNumber(element.getLineNumber());
            }
        }

        Map<String, Object> event = new HashMap<>(16);
        event.put(EventConstant.EVENT_LOG, logMagicResult);
        event.put(EventConstant.EVENT_SIGN, SIGN_EXECUTER_RESULT);
        event.put(EventConstant.EVENT_REQUEST, request);
        event.put(EventConstant.EVENT_WEBHOOK, isvWebhooks);
        SpringUtil.publishEvent(new MagicLogEvent(event));
    }

    public static void publishExecuterSuccessEvent(String executeId, String resultScope, String resultRes, String resultDesc) {
        publishExecuterResultEvent(executeId, null, resultScope, resultRes, resultDesc, null);
    }

    public static void publishExecuterErrorEvent(String executeId, String isvWebhooks, String resultScope, String resultRes, String resultDesc, Throwable error) {
        publishExecuterResultEvent(executeId, isvWebhooks, resultScope, resultRes, resultDesc, error);
    }

    public static void publishExecuterErrorEvent(R r, Throwable error) {
        publishExecuterResultEvent(r.getData().get("executeId") + "",
                r.getData().get("isvWebhooks") + "",
                r.getData().get("resultScope") + "",
                r.getData().get("resultRes") + "",
                r.getData().get("resultDesc") + "", error);
    }

}
